/*************************************************************************************************
#  Copyright (C), 20xx-20xx, xxx. Co., Ltd.
#  File Name :		spi.c
#  Author : decorn		Version : V1.0		Date : 2017-08-10
#  Description :
#	SPI BSP
#  Others :
#	None
#  Function List :
#	exch_spi_init
#	exch_get_status
#  History :
#	1. Author : decorn		Version : V1.0		Date : 2017-08-10
#		Modification: Create
#	2.
#************************************************************************************************/
#define FILE_ID_SPI

#include "spi.h"

static volatile uint8_t g_u8a_exch_dma_tx_buf[EXCH_SIZE_MAX] __attribute__((section("SPI_TX_BUF"), zero_init));
static volatile uint8_t g_u8a_exch_dma_rx_buf[EXCH_SIZE_MAX] __attribute__((section("SPI_RX_BUF"), zero_init));

void exch_spi_init(bool_t b8_is_master)//SPI初始化
{
	GPIO_InitTypeDef	GPIO_InitStructure;
	SPI_InitTypeDef		SPI_InitStructure;
	uint16_t			u16_tmp_reg	= 0u;
	
	/* Enable the SPI peripheral */
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);

	/* Enable the DMA peripheral */
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

	/* Enable SCK, MOSI, MISO and NSS GPIO clocks */
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA , ENABLE);
	/* Ready GPIO */
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB , ENABLE);

	/* SPI pin mappings */
	GPIO_PinAFConfig(GPIOA, GPIO_PinSource4, GPIO_AF_0);	/* SPI1_NSS */
	GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_0);	/* SPI1_CLK */
	GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_0);	/* SPI1_MISO */
	GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_0);	/* SPI1_MOSI */

	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
	GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_DOWN;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_Level_3;

	/* SPI NSS pin configuration */
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	/* SPI SCK pin configuration */
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	/* SPI MISO pin configuration */
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	/* SPI	MOSI pin configuration */
	GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_7;
	GPIO_Init(GPIOA, &GPIO_InitStructure);

	/* SPI configuration -------------------------------------------------------*/
	SPI_I2S_DeInit(SPI1);
	SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
	SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
	SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
	SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
	SPI_InitStructure.SPI_NSS = SPI_NSS_Hard;
	SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;//45MHZ/4=11.25M？
	SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
	SPI_InitStructure.SPI_CRCPolynomial = 7u;
	/*
	SPI初始化，前面最好别动
	*/
	if(b8_is_master == BTRUE)
	{
		/* Initializes the SPI communication */
		/*
		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
		GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
		GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_DOWN;
		GPIO_InitStructure.GPIO_Speed = GPIO_Speed_Level_3;
		GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
		GPIO_Init(GPIOA, &GPIO_InitStructure);
		GPIO_SetBits(GPIOA, GPIO_Pin_4);
		SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
		*/
		
		u16_tmp_reg	= SPI1->CR2;
		u16_tmp_reg	= u16_tmp_reg | 0x0010u;
		SPI1->CR2	= u16_tmp_reg;
		
		SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
		SPI_Init(SPI1, &SPI_InitStructure);
		/* Initialize the FIFO threshold */
		SPI_RxFIFOThresholdConfig(SPI1, SPI_RxFIFOThreshold_QF);
		/* Enable the SPI peripheral */
		/* // SPI_Cmd(SPI1, ENABLE); */
		/* Enable NSS output for master mode */
		SPI_SSOutputCmd(SPI1, ENABLE);
		
		/* SPI	Slave-Ready pin configuration */
		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
		GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
		GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_DOWN;
		GPIO_InitStructure.GPIO_Speed = GPIO_Speed_Level_3;
		GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_9;
		GPIO_Init(GPIOB, &GPIO_InitStructure);
		/* SPI	Master-Ready pin configuration */
		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
		GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
		GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_DOWN;
		GPIO_InitStructure.GPIO_Speed = GPIO_Speed_Level_3;
		GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_8;
		GPIO_Init(GPIOB, &GPIO_InitStructure);
		/*
		主SPI初始化
		*/
	}
	else 
	{
		/* Initializes the SPI communication */
		u16_tmp_reg	= SPI1->CR2;
		u16_tmp_reg	= u16_tmp_reg | 0x0010u;
		SPI1->CR2	= u16_tmp_reg;
		
		SPI_InitStructure.SPI_Mode = SPI_Mode_Slave;
		SPI_Init(SPI1, &SPI_InitStructure);

		/* Initialize the FIFO threshold */
		SPI_RxFIFOThresholdConfig(SPI1, SPI_RxFIFOThreshold_QF);
		/* SPI	Slave-Ready pin configuration */
		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
		GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
		GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_DOWN;
		GPIO_InitStructure.GPIO_Speed = GPIO_Speed_Level_3;
		GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_9;
		GPIO_Init(GPIOB, &GPIO_InitStructure);
		/* SPI	Master-Ready pin configuration */
		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
		GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
		GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_DOWN;
		GPIO_InitStructure.GPIO_Speed = GPIO_Speed_Level_3;
		GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_8;
		GPIO_Init(GPIOB, &GPIO_InitStructure);
	    /*
		从SPI初始化
		*/
	}
}

void exch_init_val(void)//初始化SPI全局变量，变量在使用之前赋初值0
{
	uint16_t	u16_idx	= 0u;
	for(u16_idx = 0u; u16_idx < EXCH_SIZE_MAX; u16_idx ++){
		g_u8a_exch_dma_tx_buf[u16_idx] = 0u;
		g_u8a_exch_dma_rx_buf[u16_idx] = 0u;
	}
}

uint8_t exch_get_status(void)//读SPI寄存器状态
{
	return SPI_RDY;
}

bool_t exch_get_slave_trigger(void)//读从SPI的触发信号，为高低电平变化
{
	bool_t		b8_is_ready		= BFALSE;
	uint16_t	u16lv_port_dat	= 0u;
	
	u16lv_port_dat = GPIO_ReadInputData(GPIOB);
	if((u16lv_port_dat & (uint16_t)U16_SET_BIT[9]) != 0u){
		b8_is_ready = BTRUE;
	}
	else{
		b8_is_ready = BFALSE;
	}
	
	return b8_is_ready;
}

void exch_set_slave_trigger(bool_t b8_ready)//写从SPI的触发信号，高低电平
{
	if(b8_ready == BTRUE){
		GPIO_SetBits(GPIOB, GPIO_Pin_9);
	}
	else{
		GPIO_ResetBits(GPIOB, GPIO_Pin_9);
	}
}

bool_t exch_get_master_ready(void)//读主SPI的ready信号 1为ready 0为busy
{
	bool_t		b8_is_ready		= BFALSE;
	uint16_t	u16lv_port_dat	= 0u;
	
	u16lv_port_dat = GPIO_ReadInputData(GPIOB);
	if((u16lv_port_dat & U16_SET_BIT[8]) != 0u){
		b8_is_ready = BTRUE;
	}
	else{
		b8_is_ready = BFALSE;
	}
	
	return b8_is_ready;
}

void exch_set_master_ready(bool_t b8_ready)//写主SPI的ready信号
{
	if(b8_ready == BTRUE)
	{
		GPIO_SetBits(GPIOB, GPIO_Pin_8);
	}
	else
	{
		GPIO_ResetBits(GPIOB, GPIO_Pin_8);
	}
}

uint8_t exch_set_dat(const volatile uint8_t *u8p_dat, uint8_t u8_len)//写发送数据
{
	uint8_t	u8_rtn	= EXCH_RTN_OK;
	uint8_t	u8_i	= 0u;
	if(u8_len <= EXCH_SIZE_MAX)
	{
		for(u8_i = 0u; u8_i < u8_len; u8_i ++)
		{
			g_u8a_exch_dma_tx_buf[u8_i] = *u8p_dat;
			u8p_dat ++;
		}
	}
	else{
		u8_rtn	= EXCH_RTN_BUF_OV;
	}
	return u8_rtn;
}

uint8_t exch_get_dat(volatile uint8_t *u8p_dat, uint8_t u8_len)//读接收到的SPI数据
{
	uint8_t	u8_rtn	= EXCH_RTN_OK;
	uint8_t	u8_i	= 0u;
	if(u8_len <= EXCH_SIZE_MAX)
	{
		for(u8_i = 0u; u8_i < u8_len; u8_i ++)
		{
			*u8p_dat = g_u8a_exch_dma_rx_buf[u8_i];
			u8p_dat ++;
		}
	}
	else
	{
		u8_rtn	= EXCH_RTN_BUF_OV;
	}
	return u8_rtn;
}

bool_t exch_spi_is_busy(void)//检查当前SPI是否忙，
{
	bool_t b8_is_busy	= BFALSE;
	
	/* Wait the SPI DMA transfers complete */
	if(DMA_GetFlagStatus(DMA1_FLAG_TC2) == RESET)
	{
		b8_is_busy = BTRUE;
	}
	if(DMA_GetFlagStatus(DMA1_FLAG_TC3) == RESET)
	{
		b8_is_busy = BTRUE;
	}
	/* The BSY flag can be monitored to ensure that the SPI communication is complete.
	This is required to avoid corrupting the last transmission before disabling 
	the SPI or entering the Stop mode. The software must first wait until TXE=1
	and then until BSY=0.*/
	if(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET)
	{
		b8_is_busy = BTRUE;
	}
	if(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == SET)
	{
		b8_is_busy = BTRUE;
	}
	/* There has a chip bug that the BSY bit cannot be cleared automatically */
	/*
	if(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY) == SET){
		b8_is_busy = BTRUE;
	}
	*/
	
	return b8_is_busy; //1是忙，0是发生完成
}

void exch_spi_disable(void)//禁止SPI,关闭SPI
{
	/* Clear DMA1 global flags */
	DMA_ClearFlag(DMA1_FLAG_GL3);
	DMA_ClearFlag(DMA1_FLAG_GL2);

	/* Disable the DMA channels */
	DMA_Cmd(DMA1_Channel2, DISABLE);
	DMA_Cmd(DMA1_Channel3, DISABLE);

	/* Disable the SPI peripheral */
	SPI_Cmd(SPI1, DISABLE);

	/* Disable the SPI Rx and Tx DMA requests */
	SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Rx, DISABLE);
	SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Tx, DISABLE);
	
	DMA_SetCurrDataCounter(DMA1_Channel2, 0u);
	DMA_SetCurrDataCounter(DMA1_Channel3, 0u);
}

void exch_spi_enable(bool_t b8_is_master)//打开SPI,数据开始传输
{
	DMA_InitTypeDef	 DMA_InitStructure;
	
	/* DMA Configuration -------------------------------------------------------*/
	DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
	DMA_InitStructure.DMA_MemoryDataSize =	DMA_MemoryDataSize_Byte;
	DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
	DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
	DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
	DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
	
	if(b8_is_master == BTRUE){
		/* DMA channel Rx of SPI Configuration */
		DMA_InitStructure.DMA_BufferSize = (uint16_t)EXCH_SIZE_MAX;
		DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)0x4001300C;
		DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t) g_u8a_exch_dma_rx_buf;
		DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
		DMA_InitStructure.DMA_Priority = DMA_Priority_High;
		DMA_Init(DMA1_Channel2, &DMA_InitStructure);
		
		/* DMA channel TX of SPI Configuration */
		DMA_InitStructure.DMA_BufferSize = (uint16_t)EXCH_SIZE_MAX;
		DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)0x4001300C;
		DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t) g_u8a_exch_dma_tx_buf;
		DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
		DMA_InitStructure.DMA_Priority = DMA_Priority_Low;
		DMA_Init(DMA1_Channel3, &DMA_InitStructure);
		
		/* Enable the SPI Rx and Tx DMA requests */
		SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Rx, ENABLE);
		SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Tx, ENABLE);

		/* Enable the SPI peripheral */
		SPI_Cmd(SPI1, ENABLE);

		/* Enable the DMA channels */
		DMA_Cmd(DMA1_Channel2, ENABLE);
		DMA_Cmd(DMA1_Channel3, ENABLE);
	}
	else{
		/* DMA channel Rx of SPI Configuration */
		DMA_InitStructure.DMA_BufferSize = (uint16_t)EXCH_SIZE_MAX;
		DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)0x4001300C;
		DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t) g_u8a_exch_dma_rx_buf;
		DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
		DMA_InitStructure.DMA_Priority = DMA_Priority_High;
		DMA_Init(DMA1_Channel2, &DMA_InitStructure);
		
		/* DMA channel Tx of SPI Configuration */
		DMA_InitStructure.DMA_BufferSize = (uint16_t)EXCH_SIZE_MAX;
		DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)0x4001300C;
		DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t) g_u8a_exch_dma_tx_buf;
		DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
		DMA_InitStructure.DMA_Priority = DMA_Priority_Low;
		DMA_Init(DMA1_Channel3, &DMA_InitStructure);

		/* Enable the SPI Rx and Tx DMA requests */
		SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Rx, ENABLE);
		SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Tx, ENABLE);
		
		/* Enable the SPI peripheral */
		SPI_Cmd(SPI1, ENABLE);
		
		/* Enable the DMA channels */
		DMA_Cmd(DMA1_Channel2, ENABLE);
		DMA_Cmd(DMA1_Channel3, ENABLE);
	}
}
